
import { MIN_DOUBLE, createDictTrie, DictTrie } from "./dictTrie"
import { MAX_WORD_LENGTH, Dag, DictUnit } from "./trie"
import { createPosTagger, PosTagger } from "./posTagger"
import { PMap, PTMap, createObj } from "./utility"
import { Segment } from "./segment"

let dictTrie_: DictTrie
let isNeedDestroy_: boolean
let tagger_: PosTagger

export interface MpSegment extends Segment {
    cut(str: string, max_word_len?: number): string[]
    tag(str: string): string[]
    getDictTrie(): DictTrie
    /* @internal */
    isUserDictSingleChineseWord(value: string): boolean
}

export function createMpSegment(dictPath: string, userDictPath = "") {
    if (!dictTrie_) {
        dictTrie_ = createDictTrie(dictPath, userDictPath)
    }
    if (!tagger_) {
        tagger_ = createPosTagger()
    }
    return {
        cut,
        tag,
        getDictTrie,
        isUserDictSingleChineseWord,
    }
}

function cut(str: string, max_word_len?: number): string[] {
    let dags: Dag[] = dictTrie_.find(str, max_word_len || MAX_WORD_LENGTH)
    CalcDp(dags)
    return cutByDag(str, dags)

}

function getDictTrie(): DictTrie {
    return dictTrie_
}

function tag(str: string) {
    return tagger_.tag(str, { cut, getDictTrie } as Segment)
}

function isUserDictSingleChineseWord(value: string) {
    return dictTrie_.isUserDictSingleChineseWord(value)
}

function CalcDp(dags: Dag[]) {
    let nextPos: number
    let p: DictUnit
    let val: number
    for (let i = dags.length - 1; i >= 0; i--) {
        let rit = dags[i]
        rit.pInfo = null
        rit.weight = MIN_DOUBLE
        if (!rit.nexts) {
            throw ("抛出错误")
        }

        for (let ii = 0, it: PMap<DictUnit>; ii < rit.nexts.length; ii++) {

            it = rit.nexts[ii]

            nextPos = it.k + 1
            p = it.v
            val = 0

            if (nextPos < dags.length && dags[nextPos].weight) {
                val += dags[nextPos].weight

            }
            if (p) {
                val += p.weight

            } else {
                val += dictTrie_.getMinWeight()

            }
            if (val > rit.weight) {
                rit.pInfo = p
                rit.weight = val

            }

        }

    }

}

function cutByDag(begin: string, dags: Dag[]) {
    let i = 0
    let words: string[] = []
    while (i < dags.length) {
        let p = dags[i].pInfo
        if (p && p.word) {
            let wr = begin.substring(i, i + p.word.length)
            words.push(wr)
            i += wr.length

        } else {
            let wr = ""
            words.push(wr)
            i++
        }
    }
    return words

}
